#include "oled.h"
#include "stdlib.h"
#include "stdio.h"
#include "oledfont.h"  	 
#include "Arduino.h"
#include "GUI.h"

uint8_t OLED_GRAM[72][5];
static unsigned char _BitTableS[8]={0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
//反显函数
void OLED_ColorTurn(uint8_t i)
{
	if(i==0)
		{
			OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
		}
	if(i==1)
		{
			OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
		}
}

//屏幕旋转180度
void OLED_DisplayTurn(uint8_t i)
{
	if(i==0)
		{
			OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
			OLED_WR_Byte(0xA1,OLED_CMD);
		}
	if(i==1)
		{
			OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
			OLED_WR_Byte(0xA0,OLED_CMD);
		}
}


//起始信号
void I2C_Start(void)
{
	OLED_SDIN_Set();
	OLED_SCLK_Set();
	OLED_SDIN_Clr();
	OLED_SCLK_Clr();
}

//结束信号
void I2C_Stop(void)
{
	OLED_SCLK_Set();
	OLED_SDIN_Clr();
	OLED_SDIN_Set();
}

//等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{
	OLED_SCLK_Set();
	OLED_SCLK_Clr();
}

//写入一个字节
void Send_Byte(uint8_t dat)
{
	uint8_t i;
	for(i=0;i<8;i++)
	{
		OLED_SCLK_Clr();//将时钟信号设置为低电平
		if(dat&0x80)//将dat的8位从最高位依次写入
		{
			OLED_SDIN_Set();
    }
		else
		{
			OLED_SDIN_Clr();
    }
		OLED_SCLK_Set();//将时钟信号设置为高电平
		OLED_SCLK_Clr();//将时钟信号设置为低电平
		dat<<=1;
  }
}

//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(uint8_t dat,uint8_t mode)
{
	I2C_Start();
	Send_Byte(0x78);
	I2C_WaitAck();
	if(mode){Send_Byte(0x40);}
  else{Send_Byte(0x00);}
	I2C_WaitAck();
	Send_Byte(dat);
	I2C_WaitAck();
	I2C_Stop();
}

//开启OLED显示 
void OLED_DisPlay_On(void)
{
	OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
	OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵
	OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
}

//关闭OLED显示 
void OLED_DisPlay_Off(void)
{
	OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
	OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵
	OLED_WR_Byte(0xAF,OLED_CMD);//关闭屏幕
}

void OLED_WR_Byte_Keep(uint8_t dat,uint8_t mode)
{
	Send_Byte(dat);
	I2C_WaitAck();
}


void OLED_Refresh(void)
{
	uint8_t i,n;
	for(i=0;i<8;i++)
	{
		OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
		OLED_WR_Byte(0x0C,OLED_CMD);   //设置低列起始地址
		OLED_WR_Byte(0x11,OLED_CMD);   //设置高列起始地址
		I2C_Start();
		Send_Byte(0x78);
		I2C_WaitAck();
		Send_Byte(0x40);
		I2C_WaitAck();
		for(n=0;n<72;n++)
			OLED_WR_Byte_Keep(OLED_GRAM[n][i],OLED_DATA);
		I2C_Stop();
    }
	
}

void OLED_RefreshPage(uint8_t page)
{
    uint8_t n=0;
    OLED_WR_Byte(0xb0+page,OLED_CMD); //设置行起始地址
    OLED_WR_Byte(0x0c,OLED_CMD);   //设置低列起始地址
    OLED_WR_Byte(0x11,OLED_CMD);   //设置高列起始地址
    for(n=0;n<72;n++)
        OLED_WR_Byte(OLED_GRAM[n][page],OLED_DATA);
}

//清屏函数
void OLED_Clear(void)
{
	uint8_t i,n;
	for(i=0;i<5;i++)
	{
	   for(n=0;n<72;n++)
        {
            OLED_GRAM[n][i]=0;//清除所有数据
        }
    }
}

void OLED_ClearPage(uint8_t page,uint8_t color)
{
	uint8_t n;
    for(n=0;n<72;n++)
    {
        OLED_GRAM[n][page]=color;//清除所有数据
    }
}

//清屏函数
void OLED_Fill(uint8_t color)
{
	uint8_t i,n;
	for(i=0;i<5;i++)
	{
	   for(n=0;n<72;n++)
        {
            OLED_GRAM[n][i]=color;//清除所有数据
        }
    }
}


//画点 
//x:0~71
//y:0~39
void OLED_DrawPoint(uint8_t x,uint8_t y)
{
	uint8_t i,m,n;
	i=y/8;
	m=y%8;
	n=1<<m;
	OLED_GRAM[x][i]|=n;
}

//清除一个点
//x:0~71
//y:0~39
void OLED_ClearPoint(uint8_t x,uint8_t y)
{
	uint8_t i,m,n;
	i=y/8;
	m=y%8;
	n=1<<m;
	OLED_GRAM[x][i]=~OLED_GRAM[x][i];
	OLED_GRAM[x][i]|=n;
	OLED_GRAM[x][i]=~OLED_GRAM[x][i];
}





//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//size:选择字体 12/16/24
//取模方式 逐列式
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t size1)
{
	uint16_t i,m,temp,size2,chr1;
	uint16_t y0=y;
	size2=(size1/8+((size1%8)?1:0))*(size1/2);  //得到字体一个字符对应点阵集所占的字节数
	chr1=chr-' ';  //计算偏移后的值
	for(i=0;i<size2;i++)
	{
		if(size1==12)
        {temp=asc2_1206[chr1][i];} //调用1206字体
		else if(size1==16)
        {temp=asc2_1608[chr1][i];} //调用1608字体
		else if(size1==24)
        {temp=asc2_2412[chr1][i];} //调用2412字体
        else if(size1==32)
        {temp=asc2_3216[chr1][i];} //调用2412字体
        else if(size1==40)
        {temp=asc2_4020[chr1][i];} //调用2412字体
		else return;

        for(m=0;m<8;m++)           //写入数据
        {
            if(temp&0x80)OLED_DrawPoint(x,y);
            else OLED_ClearPoint(x,y);
            temp<<=1;
            y++;
            if((y-y0)==size1)
            {
                y=y0;
                x++;
                break;
            }
        }
    }
}


//显示字符串
//x,y:起点坐标  
//size1:字体大小 
//*chr:字符串起始地址 
void OLED_ShowString(uint8_t x,uint8_t y,char *chr,uint8_t size1)
{
	while((*chr>=' ')&&(*chr<='~'))//判断是不是非法字符!
	{
		OLED_ShowChar(x,y,*chr,size1);
		x+=size1/2;
		if(x>72)  //换行
		{
			break;
        }
		chr++;
  }
}

//m^n
u32 OLED_Pow(uint8_t m,uint8_t n)
{
	u32 result=1;
	while(n--)
	{
	  result*=m;
	}
	return result;
}

////显示2个数字
////x,y :起点坐标	 
////len :数字的位数
////size:字体大小
void OLED_ShowNum(uint8_t x,uint8_t y,u32 num,uint8_t len,uint8_t size1)
{
	uint8_t t,temp;
	for(t=0;t<len;t++)
	{
		temp=(num/OLED_Pow(10,len-t-1))%10;
			if(temp==0)
			{
				OLED_ShowChar(x+(size1/2)*t,y,'0',size1);
            }
			else 
			{
			    OLED_ShowChar(x+(size1/2)*t,y,temp+'0',size1);
			}
  }
}


//x0,y0：起点坐标
//BMP[]：要写入的图片数组
void OLED_ShowPicture(uint8_t x,uint8_t y,uint8_t width,uint8_t length,const uint8_t *pic)
{
    //控制OLED缓存刷新图片
	uint8_t i,n;
    uint32_t j=0;

    length = length/8;
    y = y/8;

    for(i=y;i<y+length;i++)
	{
        for(n=x;n<x+width;n++)
        {
            OLED_GRAM[n][i]=pic[j];
            j++;
        }
    }


}
//OLED的初始化
void OLED_Init(void)
{

    pinMode(4,OUTPUT);
    pinMode(5,OUTPUT);
    
	delay(200);
	
	OLED_WR_Byte(0xAE,OLED_CMD); /*display off*/
	OLED_WR_Byte(0xD5,OLED_CMD); /*set osc division*/
	OLED_WR_Byte(0xF0,OLED_CMD);
	OLED_WR_Byte(0xA8,OLED_CMD); /*multiplex ratio*/
	OLED_WR_Byte(0x27,OLED_CMD); /*duty = 1/40*/
	OLED_WR_Byte(0xD3,OLED_CMD); /*set display offset*/
	OLED_WR_Byte(0x00,OLED_CMD);
	OLED_WR_Byte(0x40,OLED_CMD); /*Set Display Start Line */
	OLED_WR_Byte(0x8d,OLED_CMD); /*set charge pump enable*/
	OLED_WR_Byte(0x14,OLED_CMD);
	OLED_WR_Byte(0x20,OLED_CMD); /*Set page address mode*/
	OLED_WR_Byte(0x02,OLED_CMD);
	OLED_WR_Byte(0xA1,OLED_CMD); /*set segment remap*/
	OLED_WR_Byte(0xC8,OLED_CMD); /*Com scan direction*/
	OLED_WR_Byte(0xDA,OLED_CMD); /*set COM pins*/
	OLED_WR_Byte(0x12,OLED_CMD);
	OLED_WR_Byte(0xAD,OLED_CMD); /*Internal IREF Setting*/
	OLED_WR_Byte(0x30,OLED_CMD);
	OLED_WR_Byte(0x81,OLED_CMD); /*contract control*/
	OLED_WR_Byte(0xfF,OLED_CMD); /*72*/
	OLED_WR_Byte(0xD9,OLED_CMD); /*set pre-charge period*/
	OLED_WR_Byte(0x22,OLED_CMD);
	OLED_WR_Byte(0xdb,OLED_CMD); /*set vcomh*/
	OLED_WR_Byte(0x20,OLED_CMD);
	OLED_WR_Byte(0xA4,OLED_CMD); /*Set Entire Display On/Off*/
	OLED_WR_Byte(0xA6,OLED_CMD); /*normal / reverse*/
	OLED_WR_Byte(0x0C,OLED_CMD); /*set lower column address*/
	OLED_WR_Byte(0x11,OLED_CMD); /*set higher column address*/	
	OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/ 

    delay(200);
    OLED_Clear();
}


void OLED_Debug(char *str,bool line, uint8_t Font_size)
{
    if(line == 0)
    {
        OLED_ClearPage(0,BLACK);
        OLED_ClearPage(1,BLACK);
        OLED_ShowString(0,0,str,Font_size);
        OLED_RefreshPage(0);
        OLED_RefreshPage(1);
    }
    else
    {
        OLED_ClearPage(2,BLACK);
        OLED_ClearPage(3,BLACK);
        OLED_ShowString(0,16,str,Font_size);
        OLED_RefreshPage(2);
        OLED_RefreshPage(3);
    }
}





void WriteByteBuffer(int page,int x,unsigned  char byte)
{
	OLED_GRAM[x][page]=byte;//清除所有数据
}



void FillByte(int page,int x,unsigned  char byte)
{
    WriteByteBuffer(page,x,OLED_GRAM[x][page]|byte);
}

void FillRect(int x,int y,int width,int height)
{
	int i,j;
	int temp =(y+height-1)/8-y/8;
	if(x>SCREEN_COLUMN ||y>SCREEN_ROW)   
			return;
	for(i=x;i<x+width&&i<72;i++)
	{
		if( temp==0 )
		{
			//ScreenBuffer[y/8][i] |=_BitTableS[height-1]<<(y%8);
			FillByte(y/8,i,_BitTableS[height-1]<<(y%8));
		}
		else
		{
			//ScreenBuffer[y/8][i] |=_BitTableS[(8-y%8)-1]<<(y%8);
			FillByte(y/8,i,_BitTableS[(8-y%8)-1]<<(y%8));
			for(j=1;j<temp;j++)
			{
				//ScreenBuffer[y/8+j][i] |=0xff;
				FillByte(y/8+j,i,0xff);
			}
			//ScreenBuffer[y/8+temp][i] |=_BitTableS[(height-1+y)%8];
			FillByte(y/8+temp,i,_BitTableS[(height-1+y)%8]);
			
		}	
	}
}




